[ 00 ] design canvas · helder

helder.

An editor for working with Claude Code. One slate shell, one amber accent, IBM Plex Mono for everything that is code or label. Every layer below uses the same four surfaces, the same 24px row height and the same selection marker: 2px amber on the left, fill one step deeper.

workspace overlays menus foundations
[ 01 ] Workspace Four columns: source control · explorer · editor · agent. 1760 × 1000
helder. odynt · main
resourcesviewsadminvaults form.blade.php
Search ⌘F Auto-fit ⌘A Hidden ⌘. Note ⌘N Git ⌘G ?
Shift+Enter to commit
staged changes4
Mphpcategory.blade.php
Mphpform.blade.php
Mphpsubcategory.blade.php
Mphpdeclined-names.blade.php
changes1
Mphpdeclined-names.blade.php
4 staged · 1 unstaged
explorerodynt
app
blueprints
bootstrap
config
database
docs
lang
public
resources
css
js
markdown
views
admin
vaults
_partials
phpcategory.blade.phpM
phpform.blade.phpM
phpindex.blade.php
phpsubcategory.blade.phpM
components
conversation
help
settings
routes
tests
mdAGENTS.md
mdCLAUDE.md
jsvite.config.js
modified +1 −1
Actual Original Diff Split
1{{-- 24B — the Vault editor. `$vault === null` means create. 3--}} 4 5@php 6$isCreate = $vault === null; 7$teamClass = \App\Models\Team::class; 8$userClass = \App\Models\User::class; 9@endphp 10 11<x-layouts.app :title="$vault?->name"> 12 13<style> 14.vlt-head { 15display: flex; 16align-items: flex-end; 17gap: 20px; 18} 19 20.vlt-card { 21background: var(--color-surface-raised); 22border: 1px solid var(--color-border-default); 23border-radius: 4px; 24padding: 22px 24px; 25} 26 27.vlt-group-label { 28font-family: 'IBM Plex Mono', monospace; 29letter-spacing: .14em; 30text-transform: uppercase; 31} 32</style>
Claude Code v2.1.259 Opus 5 (1M context) · Claude Max ~/code/odynt
[ ! ] 1 MCP server needs authentication — run /mcp
Implement the vault admin screens from docs/design_handoff_vaults/README.md.
I read the handoff and the existing policies. Then I write the tests first.
Read docs/design_handoff_vaults/README.md · 412 lines Grep "VaultPolicy" · 7 hits Edit app/Policies/VaultPolicy.php
test the round trip with Playwright
[Opus 5 · 1M] odynt main ▸▸ auto mode /rc
[main][~/code/odynt]$ php artisan test --filter=Vault
PASS Tests\Feature\VaultAdminTest · 14 assertions
[main][~/code/odynt]$
⑂ main +16−12 resources/views/admin/vaults/form.blade.php ·Ln 20, Col 12·UTF-8·LF·Blade
[ 02 ] Overlays One rule: ink scrim, panel on slate-2, 8px radius, esc top right.
2a · search ⌘f
config( php md js 0 here · 226 hits · 0 files
this file
phpConfigSyncCommand.php
No matches in this file.
project226
phpcypress/e2e/Conversation/ConversationWelcome.php4
80function conversationSeedConfig(): void 99conversationSeedConfig(); 163conversationSeedConfig();
phpdatabase/seeders/DatabaseSeeder.php3
230* This row is consumed by AppData::resolveDefaultThemeConfig() 245'config' => self::guestThemeConfig(), 257private static function guestThemeConfig(): array
jscypress/e2e/blueprint-038-conversation-menu.cy.js1
163cy.url().should('eq', Cypress.config('baseUrl') + '/conversation');
mdblueprints/done/012-dialog-page/blueprint.md1
162— `config/ai.php` — providers.anthropic.api_key
files0
No file names match.
⌘← / ⌘→ column ⌘↑ / ⌘↓ row open esc
2b · shortcuts ?
Keyboard shortcuts esc
navigate
FSearch contents and names ↑↓Move through a list Open the selected item ←→Column left or right
agent
Pass the selection to the agent NOpen the project note PPass on the whole note
git
CFocus the commit message Commit the staged files GSource Control column on or off MCycle Actual · Original · Diff · Split
file
SSave this file WClose this file .Hidden files on or off
2c · project note ⌘n
Note .notes.txt To the agent ⌘P esc

I've created a design for the admin screens that manage the vaults, vault_categories and the vault_subcategories.

Implement them. Let them respect the admin policies just like agents, teams and companies have their own policies.

The design can be found here: docs/design_handoff_vaults/README.md

The vaults index page replaces /crud/vaults. Remove that code and place this feature on /admin/vaults.

saved on focus loss·412 characters
2d · open a project
helder. Open a project to begin
+ Open new project…
recent
odynt~/code/odynt
stedt~/code/stedt
loopt~/code/loopt
doen-r~/code/doen-r
vakwerk~/code/vakwerk
diagram~/code/diagram
marketingtools~/code/marketingtools
⌘↑↓ navigate open
[ 03 ] Diff Added is teal, removed is amber-deep. No green, no red.
resources/views/help/vault/declined-names.blade.php modified +1 −1 staged → actual Collapse esc
originalbefore
18{{ __('A merge writes a declined row…') }} 19</p> 20</section> 21 22<section class="odynt-help__section"> 23<h2>{{ __('The reason a row can carry') }}</h2> 24 25<p> 26{{ __('A row can carry one of eleven reason codes…') }} 27</p> 28</section>
updatedafter
18{{ __('A merge writes a declined row…') }} 19</p> 20</section> 21 22<section class="odynt-help__section is-reasons"> 23<h2>{{ __('The reason a row can carry') }}</h2> 24 25<p> 26{{ __('A row can carry one of eleven reason codes…') }} 27</p> 28</section>
[ 04 ] Details Menus, prompts, tooltips and the markdown switch. All on 24px rows.
4a · explorer menu
tests/Unit/ExampleTest.php
Pass on reference
Copy reference
Pass on file name
Copy file name
Rename file
Show in Finder
Delete file
4b · source control menu
resources/views/help/vault/declined-names.blade.php
Pass on reference
Copy reference
+Stage changes
Open diff
Discard changes
4c · pass on to agent
Pass on to agent esc
write the test for this
inserts write the test for this ⇒ tests/Unit/ExampleTest.php
insert into agent · esc cancel
4d · toolbar + tooltip
Search ⌘F Auto-fit ⌘A Hidden ⌘. Note ⌘N Git ⌘G
Hidden files: hidden — dotfiles excluded from the tree and the search. Click to show.
Auto-fit panels: on — columns re-fit on resize and focus. Click to lock the current sizes.
Project note (.notes.txt) — kept next to this project.
Tooltip: slate-3 surface, 1px border, no arrow, no shadow. The state is amber inside the sentence.
4e · markdown actual · preview
markdown Actual Preview
1You write the handover record for a 2conversation that is about to be cut. 3 4The reader is a model with no access to 5the original messages. 6 7## Sources 8 9Use only the messages, the tool results 10and the previous summary.
markdown Actual Preview

You write the handover record for a conversation that is about to be cut.

The reader is a model with no access to the original messages. Your record is the only input it gets.

Sources

Use only the messages, the tool results and the previous summary. If you cannot point to that source, delete the line.

[ 05 ] Foundations Four surfaces, one accent, six syntax colours.
surfaces and accent
#101720editor · terminal
#18202Bpanels · chrome
#232C39selection · border
#E8913Aaction · state · cursor

Amber is a reservation: active toggle, selection marker, cursor, the blinking period and the counts in the status bar. Never an amber surface as decoration.

syntax
text · #E4E7E6 variable · #BAC0C0 comment · #6C7783 keyword · #C3A6CE string · #8FBFB4 number · tag · #F0B476
+ added — #8FBFB4 op rgba(143,191,180,.12) − removed — #C4741F op rgba(196,116,31,.14)

Six colours, all muted. No green for good and no red for bad — the diff reads on shape and on the 2px rule, not on alarm.

type and rhythm
IBM Plex Mono 700 titles, labels, paths, code, shortcuts IBM Plex Sans 400 · 500 rows, menu items, tooltips, running text
row height · 24pxchrome · 44px code line · 20pxstatus bar · 28px radius control · 2pxradius overlay · 8px border · 1pxmarker · 2px amber
row states
rest
hover — fill one step deeper
selected — 2px amber on the left
not available — 40%

No movement, no shadow, no scale. Colour only, 160ms. The only animation in the whole editor is the blinking cursor and the period in the mark.

[ 06 ] Code colours The same six colours across every language. Nothing bold, nothing italic — weight stays 400 so the column reads flat.
6a · javascript
js resources/js/symbols-service.js javascript
1// One request per file. The tree keeps the last answer. 2 3import { cache } from './cache.js'; 4 5const ENDPOINT = '/api/symbols'; 6const TIMEOUT = 2500; 7 8export async function readSymbols(path, signal) { 9if (cache.has(path)) return cache.get(path); 10 11const res = await fetch(`${ENDPOINT}?p=${path}`, { signal }); 12 13if (!res.ok) { 14throw new Error(`symbols: ${res.status}`); 15} 16 17const rows = await res.json(); 18cache.set(path, rows); 19 20return rows; 21}
6b · php
php app/Console/Commands/ConfigSyncCommand.php php
1<?php 2 3declare(strict_types=1); 4 5namespace App\Console\Commands; 6 7use App\Models\Config; 8 9/** Writes one row per config group. */ 10final class ConfigSyncCommand extends Command 11{ 12protected $signature = 'config:sync'; 13 14public function handle(): int 15{ 16$created = 0; 17 18foreach ($this->registry() as $key => $class) { 19$row = Config::query()->find($key); 20 21if ($row === null) { 22$created++; 23} 24} 25 26return self::SUCCESS; 27} 28}
6c · css
css resources/css/panels.css css
1/* Four surfaces, one accent. Nothing else. */ 2 3:root { 4--editor: #101720; 5--panel: #18202B; 6--accent: #E8913A; 7} 8 9.row { 10display: flex; 11gap: 8px; 12height: 24px; 13border-left: 2px solid transparent; 14transition: background 160ms ease-out; 15} 16 17.row:hover { 18background: #1E2733; 19} 20 21.row[aria-selected='true'] { 22background: #232C39; 23border-left-color: var(--accent); 24}
6d · markdown preview
md blueprints/046-symbols/blueprint.md Actual Preview
blueprint · 046

Symbols in the tree

The explorer shows classes and functions under a file once the file is open. The list comes from one request per file and it is cached for the session.

What it changes

A row gains one child level. Nothing else in the tree moves.
The endpoint answers in under 250ms for a file of 2000 lines.
A parse error leaves the file row untouched and logs once.
A symbol list nobody asked for is a symbol list nobody reads. Open the file first.
// the shape one row returns { rel: 'class', line: 42, kind: 'php' }
stepfilestate
Endpointroutes/api.phpdone
Tree levelexplorer.jsopen

Full contract in docs/symbols.md